package com.zmn.oms.services.impl.report;

import com.google.common.collect.Lists;
import com.zmn.base.common.data.dubbo.interfaces.area.AreaListRemoteService;
import com.zmn.base.product.common.consts.BaseProductConsts;
import com.zmn.base.product.common.dto.categ.CategServProductDRO;
import com.zmn.base.product.common.query.categ.ForeignCategServProductQuery;
import com.zmn.base.product.dubbo.interfaces.categ.serv.CategServProductListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto.KvDTO;
import com.zmn.common.dto2.Option;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.pager.Pages;
import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.bo.work.EsQueryBuilder;
import com.zmn.oms.model.entity.report.GD114;
import com.zmn.oms.model.entity.report.GD114Query;
import com.zmn.oms.model.entity.report.newOrderCountQuery;
import com.zmn.oms.model.entity.work.OrderWorkQuery;
import com.zmn.oms.services.interfaces.report.WorkReportService;
import org.apache.dubbo.config.annotation.Reference;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedTopHits;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class WorkReportServiceImpl implements WorkReportService {

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private AreaListRemoteService areaListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private CategServProductListRemoteService categServProductListRemoteService;
    @Resource
    private OrderWorkEsBService orderWorkEsBService;

    private static Map<String, Integer> resultCallback(Aggregation aggregation) {
        SearchHit[] hits = ((ParsedTopHits) aggregation).getHits().getHits();
        int count = 0;
        for (SearchHit hit : hits) {
            Map<String, Object> source = hit.getSourceAsMap();
            //noinspection unchecked
            List<Map<String, Object>> operateList = (List<Map<String, Object>>) source.get("operateList");
            for (Map<String, Object> stringObjectMap : operateList) {
                Integer operateType = (Integer) stringObjectMap.get("operateType");
                Integer operatorId = (Integer) stringObjectMap.get("operatorId");
                if (Objects.equals(OrderConsts.ORDER_OP_TYPE_INPUT, operateType) && !NumberUtil.isNullOrZero(operatorId) && operatorId != 1) {
                    count++;
                    break;
                }
            }
        }
        return Collections.singletonMap("specialSeat", count);
    }

    @Override
    public List<GD114> listGD114ReportByQuery(GD114Query gd114Query) throws OmsBaseException {
        return Lists.newArrayList();
        /*int GUANGDONG_PROVINCE_ID = 440000;
        ResponseDTO<OptionData<Integer>> listResponseDTO = areaListRemoteService.listOptionCityByProvinceId(GUANGDONG_PROVINCE_ID);
        List<Option<Integer>> cityListDto = listResponseDTO.getData().getOptions();
        if (!listResponseDTO.isSuccess() && CollectionUtils.isEmpty(cityListDto)) {
            throw new OmsBaseException("地区远程接口调用失败,无法初始化结果集");
        }
        List<Integer> cityIdList = cityListDto.stream().map(Option<Integer>::getValue).collect(Collectors.toList());

        LoggerUtil.info(this.getClass(), "[广东114报表]gd114Query = [" + gd114Query + "]");
        String type = Optional.ofNullable(gd114Query.getType()).orElse("city");
        Date endDate = Optional.ofNullable(gd114Query.getEndDate()).orElse(DateUtil.getNow());
        String nowFormatted = DateUtil.getNowFormatted("yyyy-MM-dd") + " 00:00:00";
        Date startDate = Optional.ofNullable(gd114Query.getStartDate()).orElse(DateUtil.parse(nowFormatted));
        LoggerUtil.info(this.getClass(), "[广东114报表]startDate = [" + startDate + "]endDate = [" + endDate + "]");
        EsAggBuilder.BuilderInit builder = EsAggBuilder.getBuilder();
        OrderWorkFilter defaultTerm = new OrderWorkFilter();
        defaultTerm.setCityIdList(cityIdList);
        defaultTerm.setWorkType(Collections.singletonList(OrderConsts.ORDER_TYPE_NEW));
        defaultTerm.setDuplicate(GlobalConsts.NO);
        EsAggBuilder.BuilderWorker<GD114> builderWorker;
        if ("categ".equals(type)) {
            //noinspection unchecked
            builderWorker = builder.init(elasticsearchRestTemplate, "categOneId", new EsOrderAggBuilderCallbackImpl(), defaultTerm, getCategGd114Map());
        } else {
            //noinspection unchecked
            builderWorker = builder.init(elasticsearchRestTemplate, "cityId", new EsOrderAggBuilderCallbackImpl(), defaultTerm, getCityGD114Map(cityListDto));
        }

        return builderWorker.query(query -> {
            query.setChannelIdList(Collections.singletonList(1024));
            query.setReceiveTime(DateUtil.dateFormatToString(startDate, DateUtil.FORMAT_DEFAULT) + "," + DateUtil.dateFormatToString(endDate, DateUtil.FORMAT_DEFAULT));
            return AggregationBuilders.topHits("hits").fetchSource(new String[]{"operateList"}, new String[]{}).size(100000);
        }).mapping(WorkReportServiceImpl::resultCallback, GD114.class).getResult();*/
    }

    @Override
    public ArrayList<KvDTO<Integer, Integer>> getNewOrderCount(newOrderCountQuery orderCountQuery) {
        OrderWorkQuery orderWorkQuery = new OrderWorkQuery();
        orderWorkQuery.setWorkType(Collections.singletonList(OrderConsts.ORDER_TYPE_NEW));
        orderWorkQuery.setDuplicate(GlobalConsts.NO);
        orderWorkQuery.setReceiveTime(DateUtil.toString(orderCountQuery.getStartTime()) + ',' + DateUtil.toString(orderCountQuery.getEndTime()));
        orderWorkQuery.setCompanyIdList(CollectionUtils.isEmpty(orderCountQuery.getCompanyIdList()) ? null : orderCountQuery.getCompanyIdList());
        orderWorkQuery.setCityIdList(CollectionUtils.isEmpty(orderCountQuery.getCityIdList()) ? null : orderCountQuery.getCityIdList());
        orderWorkQuery.setPlat(GlobalConsts.PLAT_MARK_ZMN);
        BoolQueryBuilder boolQueryBuilder = null;
        try {
            boolQueryBuilder = EsQueryBuilder.getQuery(orderWorkQuery);
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
        Pages pages = new Pages();
        pages.setPageIndex(1);
        pages.setPageSize(10);
        PageRequest pageRequest = EsQueryBuilder.getPageRequest(pages);
        NativeSearchQuery query = new NativeSearchQuery(boolQueryBuilder);
        query.setPageable(pageRequest);
        String groupBy;
        Boolean isGroupByCompanyId = orderCountQuery.isGroupByCompanyId;
        if (Objects.isNull(isGroupByCompanyId)||!isGroupByCompanyId) {
            groupBy = "cityId";
        } else {
            groupBy = "companyId";
        }
        TermsAggregationBuilder builder = AggregationBuilders.terms(groupBy).field(groupBy).size(100000);
        query.addAggregation(builder);
        Aggregations count = orderWorkEsBService.getAggregationsByQuery(query);
        ParsedLongTerms cityId = count.get(groupBy);
        List<? extends Terms.Bucket> buckets = cityId.getBuckets();
        ArrayList<KvDTO<Integer, Integer>> objects = Lists.newArrayList();
        buckets.forEach(bucket -> {
            int cityIad = bucket.getKeyAsNumber().intValue();
            int counat = new Long(bucket.getDocCount()).intValue();
            objects.add(new KvDTO<>(cityIad, counat));
        });
        return objects;
    }

    private Map<Integer, GD114> getCityGD114Map(List<Option<Integer>> cityListDto) throws OmsBaseException {
        //初始化数据map
        return cityListDto.stream().collect(Collectors.toMap(Option<Integer>::getValue, o -> new GD114(o.getLabel(), 0, 0)));
    }

    private Map<Integer, GD114> getCategGd114Map() throws OmsBaseException {
        ForeignCategServProductQuery build = ForeignCategServProductQuery
                .builder()
                .showType(BaseProductConsts.ERP_SHOW_TYPE)
                .build();
        ResponseDTO<List<CategServProductDRO>> byServiceCategId = categServProductListRemoteService.listByQuery(build);
        List<CategServProductDRO> items = byServiceCategId.getData();
        if (!byServiceCategId.isSuccess() && CollectionUtils.isEmpty(items)) {
            throw new OmsBaseException("服务分类远程接口调用失败,无法初始化结果集");
        }
        return items.stream().collect(Collectors.toMap(CategServProductDRO::getCategId, o -> new GD114(o.getCategName(), 0, 0)));
    }


}
